/*
 * session.cpp
 *
 *  Created on: 2019-1-12
 *      Author: work
 */

#include <dm/session/session.hpp>

#include <dm/session/sessionmgr.hpp>
#include <dm/session/modgen.hpp>
#include <dm/os/log/logger.hpp>

namespace dm{
namespace session{

const char* logModule = "CSession.session.dm";

CSession::CSession():m_deadline(),m_mod(0),m_userId(-1){
	for( int i=0;i<MaxRts;++i )
		m_rts[i] = 0;
	for( int i=0;i<MaxLog;++i )
		m_logs[i] = 0;
	for( int i=0;i<MaxTimed;++i )
		m_timeds[i] = 0;
}


bool CSession::init( const userid_t& id,const dm::CTimeStamp& n,const dm::CTimeStamp::s_t& aliveSecs ){
	msharelock_exclusive_t ml(m_lock);
	if( isIdle(n) ){
		m_userId = id;
		m_deadline = n;
		m_deadline.addSec(aliveSecs);
		m_mod = CModGen::ins().gen();

		for( int i=0;i<MaxRts;++i )
			m_rts[i] = 0;
		for( int i=0;i<MaxLog;++i )
			m_logs[i] = 0;
		for( int i=0;i<MaxTimed;++i )
			m_timeds[i] = 0;

		return true;
	}

	return false;
}

bool CSession::update( const mod_t& m,const userid_t& id,const dm::CTimeStamp& n,const dm::CTimeStamp::s_t& aliveSecs ){
	msharelock_exclusive_t ml(m_lock);
	if( m_mod==m && m_userId==id && n<m_deadline ){
		m_deadline = n;
		m_deadline.addSec(aliveSecs);
		return true;
	}

	return false;
}

bool CSession::free( const mod_t& m,const userid_t& id ){
	msharelock_exclusive_t ml(m_lock);
	if( m_mod==m && m_userId==id ){
		free();
		return true;
	}

	return false;
}

bool CSession::isIdle( const dm::CTimeStamp& n )const{
	if( m_userId==-1 || m_mod==0 || m_deadline<=n )
		return true;
	return false;
}

bool CSession::isTimeout( const dm::CTimeStamp& n )const{
	return m_deadline < n;
}

int CSession::rtsCount()const{
	int c = 0;
	for( int i=0;i<MaxRts;++i ){
		if( m_rts[i] )
			++c;
	}

	return c;
}

int CSession::logCount()const{
	int c = 0;
	for( int i=0;i<MaxLog;++i ){
		if( m_logs[i] )
			++c;
	}

	return c;
}

int CSession::timedCount()const{
	int c = 0;
	for( int i=0;i<MaxTimed;++i ){
		if( m_timeds[i] )
			++c;
	}

	return c;
}

CRtsMonitor* CSession::getFreeRts(){
	msharelock_exclusive_t ml(m_lock);
	for( int i=0;i<MaxRts;++i ){
		if( m_rts[i]!=0 && NULL==CSessionMgr::ins()->m_rts.get(m_rts[i],0) ){
			log().info(THISMODULE "%d]rt monitor %llX timeout",i,m_rts[i]);
			m_rts[i] = 0;
		}

		if( m_rts[i]==0 ){
			CRtsMonitor* rt = CSessionMgr::ins()->m_rts.getNew();
			if( rt ){
				m_rts[i] = rt->mod();
				log().info(THISMODULE "%d]get rt monitor %llX",i,m_rts[i]);
				return rt;
			}else{
				log().warnning(THISMODULE "no free rt monitor %d",CRtsMonitorMgr::Size);
				return NULL;
			}
		}
	}

	log().warnning(THISMODULE "no free rt monitor %d",MaxRts);
	return NULL;
}

CRtsMonitor* CSession::getRts( const mod_t& mod ){
	msharelock_exclusive_t ml(m_lock);
	for( int i=0;i<MaxRts;++i ){
		if( m_rts[i]==mod ){
			CRtsMonitor* rt = CSessionMgr::ins()->m_rts.get(mod);
			if( rt )
				return rt;

			log().warnning(THISMODULE "%d] rt monitor %llX timeout",i,mod);
			m_rts[i] = 0;
			return NULL;
		}
	}

	log().warnning(THISMODULE "no rt monitor %llX",mod);
	return NULL;
}

CLogMonitor* CSession::getFreeLog(){
	msharelock_exclusive_t ml(m_lock);
	for( int i=0;i<MaxLog;++i ){
		if( m_logs[i]!=0 && CSessionMgr::ins()->m_logs.get(m_logs[i],0)==NULL ){
			log().info(THISMODULE "%d]log monitor %llX timeout",i,m_logs[i]);
			m_logs[i] = 0;
		}

		if( m_logs[i]==0 ){
			CLogMonitor* rt = CSessionMgr::ins()->m_logs.getNew();
			if( rt ){
				m_logs[i] = rt->mod();
				log().info(THISMODULE "%d] get log monitor %llX",i,m_logs[i]);
				return rt;
			}else{
				log().warnning(THISMODULE "no free log monitor %d",CLogMonitorMgr::Size);
				return NULL;
			}
		}
	}

	log().warnning(THISMODULE "no free log monitor %d",MaxLog);
	return NULL;
}

CLogMonitor* CSession::getLog( const mod_t& mod ){
	msharelock_exclusive_t ml(m_lock);
	for( int i=0;i<MaxLog;++i ){
		if( m_logs[i]==mod ){
			CLogMonitor* rt = CSessionMgr::ins()->m_logs.get(mod);
			if( rt )
				return rt;
			log().warnning(THISMODULE "%d] log monitor %llX timeout",i,mod);
			m_logs[i] = 0;
			return NULL;
		}
	}

	log().warnning(THISMODULE "no log monitor %llX",mod);
	return NULL;
}

CTimedMonitor* CSession::getFreeTimed(){
	msharelock_exclusive_t ml(m_lock);
	for( int i=0;i<MaxTimed;++i ){
		if( m_timeds[i] && NULL==CSessionMgr::ins()->m_tds.get(m_timeds[i]) ){
			log().info(THISMODULE "%d]ts data monitor %llX timeout",i,m_timeds[i]);
			m_timeds[i] = 0;
		}

		if( m_timeds[i]==0 ){
			CTimedMonitor* rt = CSessionMgr::ins()->m_tds.getNew();
			if( rt ){
				m_timeds[i] = rt->mod();
				log().info(THISMODULE "%d]get ts data monitor %llX",i,m_timeds[i]);
				return rt;
			}else{
				log().warnning(THISMODULE "no free ts data monitor %d",CTimedMonitorMgr::Size);
				return NULL;
			}
		}
	}

	log().warnning(THISMODULE "no free ts data monitor %d",MaxTimed);
	return NULL;
}

CTimedMonitor* CSession::getTimed( const mod_t& mod ){
	msharelock_exclusive_t ml(m_lock);
	for( int i=0;i<MaxTimed;++i ){
		if( m_timeds[i]==mod ){
			CTimedMonitor* rt = CSessionMgr::ins()->m_tds.get(mod);
			if( rt )
				return rt;
			log().warnning(THISMODULE "%d]ts data monitor %llX timeout",i,mod);
			m_timeds[i] = 0;
			return NULL;
		}
	}

	log().warnning(THISMODULE "no ts data monitor %llX",mod);
	return NULL;
}

void CSession::free(){
	msharelock_exclusive_t ml(m_lock);
	if( m_userId && m_mod ){
		m_userId = 0;
		m_mod = 0;

		CSessionMgr* sm = CSessionMgr::ins();

		for( int i=0;i<MaxRts;++i ){
			if( m_rts[i] )
				sm->m_rts.free(m_rts[i]);
		}

		for( int i=0;i<MaxLog;++i ){
			if( m_logs[i] )
				sm->m_logs.free(m_logs[i] );
		}

		for( int i=0;i<MaxTimed;++i ){
			if( m_timeds[i] )
				sm->m_tds.free(m_timeds[i]);
		}
	}
}

}
}
